package com.scu.baseline.service.impl;

import com.scu.baseline.pojo.User;
import com.scu.baseline.mapper.UserMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.jdbc.Null;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 用户表(User)表服务实现类
 *
 * @author lotswn
 * @since 2022-06-13 22:53:07
 * @version 1.0
 */
@Service("userService")
public class UserServiceImpl {
    @Resource
    private UserMapper userMapper;

    /**
     * 根据模糊条件查询总个数
     *
     * @return 返回查询到的总个数
     */
    public Map<String, Object> selectCount(String name, String auth, String departmentid) {
        Map<String, Object> map = new HashMap<>();
        // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("list", this.userMapper.selectCount(name,auth,departmentid));
        return map;
    }

    /**
     * 查询所有数据
     * @return  返回所有数据
     */
    public Map<String, Object> selectAll() {
        Map<String, Object> map = new HashMap<>();
        // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("list", this.userMapper.selectAll());
        return map;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    public Map<String, Object> selectById(Integer id) {
        Map<String, Object> map = new HashMap<>();
        // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("obj", this.userMapper.selectById(id));
        return map;
    }

    /**
     * 查询分页数据
     *
     * @param page 查询起始位置
     * @param name 查询条数
     * @return 对象列表
     */
    public Map<String, Object> selectByPage(int page, String name,String auth,String departmentid) {
    // 获取当前表中的总记录
        int tableCount = this.userMapper.selectCount(name,auth,departmentid);
        // 总页码计算   (总条数 - 1) / 每页显示条数  + 1
        // (100 - 1) / 10 + 1 = 10        (101 - 1) / 10 + 1 = 11      (99 - 1) / 10 + 1 = 10
        int pageCount = (tableCount - 1) / 10 + 1;
        // 计算每页开始的下标值
        int index = (page - 1) * 10;
        Map<String, Object> map = new HashMap<>();
        map.put("code", 0);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "查询成功!");
        map.put("pageCount", pageCount);  // 查询的记录总页码
        map.put("count", tableCount);     // 当前表中的总条数
        map.put("data", this.userMapper.selectByPage(index, name, auth, departmentid));
        return map;
    }

    /**
     * 新增数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    public Map<String, Object> register(User user) {
        if(user.getAuth() == null) {user.setAuth(0);}
        user.setUserimg("./userimg.png");
        if(user.getDepartmentid() == null) {user.setDepartmentid(0);}
        String password_md5 = md5(user.getUsername(), user.getPassword());
        user.setPassword(password_md5);
        this.userMapper.register(user);                  // 注册一个新用户
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "新增成功");
        map.put("data", user);
        return map;
    }
    /**
     * 通过ID更新单条数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    public Map<String, Object> updateById(User user) {
        User olduser = this.userMapper.selectById(user.getId());
        if(user.getPassword( )!=" " && user.getPassword( )!=null)
        {
            String password_md5 = md5(olduser.getUsername(), user.getPassword());
            user.setPassword(password_md5);
        }
        this.userMapper.updateById(user);
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前后端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "更新成功");
        return map;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    public Map<String, Object> deleteById(String id) {
        this.userMapper.deleteById(id);
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "删除成功");
        return map;
    }

    /**
     * 通过指定一个唯一的用户名，查找此用户的完整资料，如果没有找到，则返回null
     * @param username  用户名
     * @return          如果查询到，则返回此用户的完成数据对象，如果没有查到，则返回null
     */
    public User getUser(@Param("username") String username) {
        return userMapper.getUser(username);
    }


    /**
     * 客户端用户登录，如果没有查到，则返回null
     * @param username  用户名
     * @param password  密码
     * @return  如果查询到，则返回此用户的完成数据对象，如果没有查到，则返回null
     */
    public Map<String, Object> clientlogin(String username, String password) {
        String password_md5 = md5(username, password);
        System.out.println(username);
        Map<String, Object> map = new HashMap<>();
        try {
            User user = getUser(username);
            System.out.println(user.getPassword());
            System.out.println(password_md5);
            if(user.getPassword().equals(password_md5)) {
                map.put("code", 200);
                map.put("msg", "登录成功！");
            }
            else {
                map.put("code", 501);
                map.put("msg", "用户名/密码不匹配！");
            }
        }
        catch (NullPointerException e)
        {
            map.put("code", 503);
            map.put("msg", "账户不存在！");
        }
        return map;
    }

    /**
     * 用户登录，如果没有查到，则返回null
     * @param username  用户名
     * @param password  密码
     * @return  如果查询到，则返回此用户的完成数据对象，如果没有查到，则返回null
     */
    public Map<String, Object> login(String username, String password) {
        Map<String, Object> map = new HashMap<>();
        Subject subject = SecurityUtils.getSubject();
        // shiro权限认证主体对象
        if (!subject.isAuthenticated()) {
            UsernamePasswordToken upToken = new UsernamePasswordToken(username, password);    // shiro权限认证类型
            upToken.setRememberMe(true);                                                     // 用户登录时效性
            try {
                subject.login(upToken);    // 调用realm认证用户权限  如果密码比对成功，则通过此方法
                map.put("code", 200);
                map.put("msg", "登录成功");
            } catch (IncorrectCredentialsException ice) {
                map.put("code", 501);
                map.put("msg", "用户名/密码不匹配！");
            } catch (LockedAccountException lae) {
                map.put("code", 502);
                map.put("msg", "账户已被冻结！");
            } catch (UnknownAccountException uae) {
                map.put("code", 503);
                map.put("msg", "账户不存在！");
            } catch (AuthenticationException ae) {
                System.out.println(ae.getMessage());
                map.put("code", 504);
                map.put("msg", "服务繁忙，请稍候重试！");
            }
        }
        return map;
    }

    /**
     * 注册时，进行shiro加密，返回加密后的结果，如果在加入shiro之前，存在用户密码不是此方式加密的，那么将无法登录
     * 使用用户名作为盐值
     * @param username  用户名
     * @param password  密码
     * @return          返回加密加盐之后的密码格式内容
     */
    private String md5(String username, String password){
        String hashAlgorithmName = "MD5";                   // 加密方式
        ByteSource salt = ByteSource.Util.bytes(username);  // 以账号转换为字节码，再作为盐值
        int hashIterations = 11;                            // 加密11次 可以自定义次数  加密的次数过程，会影响服务性能
        return new SimpleHash(hashAlgorithmName, password, salt, hashIterations).toString();
    }
}